#include "Game.h"

int Game::counter = 0;

User * Game::findPlayerById(int id_){
		vector <User *>::iterator it;

		for(it=Players.begin(); it!=Players.end();++it)
			if((**it).getId()==id_)
				return *it;

		return NULL;
	
	};

void Game::removePlayer(User *a){
		vector<User *>::iterator it;

		for(it=Players.begin(); it!=Players.end();++it)
			if((*it)==a){
				Players.erase(it);
				a->setGameId(0);
				return;
			}		

			perror("Nie ma takiego gracza do usuniecia z gry\n");
			exit(1);
	};


void Game::addPlayer(User *a){
		Players.push_back(a);
		a->setGameId(id);
};

void Game::sendToAll(int code) {
		vector<User*>::iterator it;
		for (it = Players.begin(); it != Players.end(); it++)
			(*it)->sendToClient(code);
	}

	void Game::sendToAll(int code, string data) {
		vector<User*>::iterator it;
		for (it = Players.begin(); it != Players.end(); it++)
			(*it)->sendToClient(code, data);
	}
	;

	void Game::sendToAll(int code, char * tab) {
		vector<User*>::iterator it;

		for (it = Players.begin(); it != Players.end(); it++)
			(*it)->sendToClient(code, tab);

	}

	void Game::sendToAllWithoutOne(int code, User *user) {
			vector<User*>::iterator it;

			for (it = Players.begin(); it != Players.end(); it++) {
				if ((*it) != user)
					(*it)->sendToClient(code);
			}
		}

	void Game::sendToAllWithoutOne(int code, char *bufor, User *user) {
		vector<User*>::iterator it;

		for (it = Players.begin(); it != Players.end(); it++) {
			if ((*it) != user)
				(*it)->sendToClient(code, bufor);
		}
	}

	// DONE
	void Game::sendToAllWithoutOne(int code, string data, User *user) {
		vector<User*>::iterator it;

		for (it = Players.begin(); it != Players.end(); it++)
			if ((*it) != user)
				(*it)->sendToClient(code, data);
	}
	;

	//TODO isSomeoneWinner
	bool isWinnerOfGame(User * user) {
		return user->getScores() >= SCORES_MAX;
	}
	; /* sprawdza czy wygrany w ostatniej rundzie nie przekroczy??? limitu punktowego */

	bool Game::checkIfGuessed(User *user, string pun_) {
		if (round->isPun(pun_)) {
			round->setWinner(user);
			round->setState(S_GUESSED);
			return true;
		} else
			return false;
	}

	User * Game::findDrawer() {
		Players[drawerId]->setDrawer(false);

		if (drawerId < Players.size() - 1) {
			drawerId++;
			Players[drawerId]->setDrawer(true);
			return Players[drawerId];
		} else{
			drawerId = 0;

		Players[drawerId]->setDrawer(true);
		return Players[drawerId];
		}
	}

	void Game::clearScores(){
		vector<User *>::iterator it;

		for(it=Players.begin();it!=Players.end();it++)
			(*it)->setScores(0);
	}

	string Game::pickPun() {

		srand(time(NULL));

		int index = 0;

		if (Puns->size() > 0)
			index = rand() % Puns->size();
		else
			perror("Blad z haslami!");

		return Puns->at(index);
	}
	;

	string Game::createRankingMsg() {
		vector<User *>::iterator it;
		ostringstream ss;

		for (it = Players.begin(); it != Players.end(); it++) {
			ss << (*it)->getLogin();
			ss << "#";
			ss << (*it)->getScores();
			ss << "#";
		}

		return ss.str();
	}

	void Game::gameLoop() {

		// dopoki trwa gra
		while (started) {

			// uruchom nowa runde, wylosuj haslo
			round = new Round(pickPun());
			User * drawer;

			//wyznacz kolejnego rysujacego
			drawer = findDrawer();

			drawer->sendToClient(S_PUN_FOR_DRAWER, round->getPun());
			sendToAllWithoutOne(S_END_OF_ROUND,drawer);

			// dopoki trwa runda
			while (!round->isTimeOut() && started && round->getState() == RUN) {sleep(1);}

			// jesli TIMEOUT
			if (round->getState() != S_GUESSED) {
				if (Players.size() > 1) {
					if(round->getState() == TIMEOUT){
						sendToAll(CHAT_MESSAGE,(string)"Runda zakonczona. Skonczyl sie czas.");
						sendToAll(CHAT_MESSAGE, (string)"Haslem bylo:" + round->getPun());
					}
					sendToAll(S_UPDATE_RANKING,createRankingMsg());
					started=true;
				}else{
					sendToAll(CHAT_MESSAGE, (string)"Haslem bylo:" + round->getPun());
					sendToAll(CHAT_MESSAGE,(string)"Gra zakonczona");
					sendToAll(S_UPDATE_RANKING,createRankingMsg());
					sendToAll(S_END_OF_GAME);
				}
			} else {	//jesli ktos odgadl
				User * user = round->getWinner();
				updateScores(user);
				if (isWinnerOfGame(round->getWinner())) {
					started = false;
					clearScores();
					sendToAll(S_UPDATE_RANKING, createRankingMsg());
					sendToAll(S_END_OF_GAME);
					sendToAll(CHAT_MESSAGE, (string)"Haslem bylo:" + round->getPun());
					user->sendToClient(CHAT_MESSAGE, createYouWinMsg(user));
					sendToAllWithoutOne(CHAT_MESSAGE,
							createGameWinnerMsg(user), user);
				} else {
					sendToAll(CHAT_MESSAGE, (string)"Haslem bylo:" + round->getPun());
					sendToAll(CHAT_MESSAGE, createRoundWinnerMsg(user));
					sendToAll(S_UPDATE_RANKING, createRankingMsg());
				}
			}

			delete round;
		}
	}

	void Game::start() {
		setStarted(true);
		pthread_t thread;
		pthread_create(&thread, NULL, gameLoopThread, (void*) this);
	}

	void *gameLoopThread(void * gamePtr){
		Game* game;
		game=(Game*)gamePtr;
		game->gameLoop();

	}
